package com.zm.rpc.server.channel.handler;

import java.util.List;

import org.apache.log4j.Logger;

import com.zm.rpc.protocol.Header;
import com.zm.rpc.protocol.RpcProtocol;
import com.zm.rpc.protocol.enums.RequestType;
import com.zm.rpc.server.serializer.ISerializer;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;

public class RpcDecoder extends ByteToMessageDecoder {
    private static final Logger log = Logger.getLogger(RpcDecoder.class);

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf byteBuf, List<Object> out) throws Exception {
        RpcProtocol<Object> protocol = this.buildProtocol(byteBuf);
        out.add(protocol);
    }

    private RpcProtocol<Object> buildProtocol(ByteBuf byteBuf) {

        RpcProtocol<Object> p = new RpcProtocol<>();
        p.setHeader(this.buildHeader(byteBuf));
        p.setContext(buildContext(byteBuf, p.getHeader()));
        return p;
    }

    private Header buildHeader(ByteBuf byteBuf) {
        short magic = byteBuf.readShort();
        byte serialType = byteBuf.readByte();
        byte rt = byteBuf.readByte();
        long reqid = byteBuf.readLong();
        int size = byteBuf.readInt();
        Header header = new Header();
        header.setMagic(magic);
        header.setSerialType(serialType);
        header.setReqType(rt);
        header.setReqId(reqid);
        header.setDataSize(size);
        return header;
    }

    private Object buildContext(ByteBuf byteBuf, Header header) {
        byte[] buf = new byte[header.getDataSize()];
        byteBuf.readBytes(buf);

        Object o = null;
        ISerializer serializer = ISerializer.getSerializer(header.getSerialType());
        RequestType requestType = RequestType.valueOf(header.getReqType());

        o = serializer.deserialize(buf, requestType.getRequestContextClass());
    

        return o;
    }

}
